.Dd September 20, 2025
.Dt R_MUTA 3
.Os
.Sh NAME
.Nm r_muta
.Nd radare2 mutation/cryptography library
.Sh SYNOPSIS
.In r_muta.h
.Pp
.Sh DESCRIPTION
The r_muta facility implements a small plugin-based framework for data transformations used across radare2. It exposes a thin, consistent API to list available plugins (hashers, encoders, ciphers, small transforms), create sessions, configure keys/IVs and stream data through plugins to produce outputs. The design focuses on reusability from other core libraries (for example, the hashing helper in `libr/muta/hash/hash.c`) so callers can treat most algorithms uniformly.
.Sh INITIALIZATION
The context object represents the global registry of available mutation plugins. Allocate it once when you need to query or create plugin sessions, and free it after all sessions are released.
.Ft RMuta *
.Fn r_muta_new "void"
.Pp
Creates and returns a new mutation context with bundled plugins registered.
.Pp
.Ft void
.Fn r_muta_free "RMuta *cry"
.Pp
Releases the context and all internal resources. Do not use a session after its parent context has been freed.
.Sh SESSIONS
Plugins are used via sessions. A session is an instance of a plugin (for example, an AES or a hash) and keeps per-operation state. Typical lifecycle: create session -> set key/iv (if applicable) -> update() -> end() -> get_output() -> free session.
.Ft RMutaSession *
.Fn r_muta_use "RMuta *cry" "const char *algo"
.Pp
Creates a session for a plugin selected by name (example names: "aes-ecb", "aes-cbc", "base64", "xor", "sha1"). Returns NULL if the plugin is not found.
.Pp
.Ft RMutaSession *
.Fn r_muta_new_session "RMuta *mu" "const char *algo" "RMutaOptions *opt"
.Pp
Like `r_muta_use`, but accepts an `RMutaOptions` structure to provide plugin-specific options during session creation.
.Pp
.Ft void
.Fn r_muta_session_free "RMutaSession *cj"
.Pp
Frees session state. Always call this when finished with a session to avoid leaks.
.Sh KEY AND IV SETUP
Most symmetric ciphers require a key and many block-based modes require an IV. Set these on the session before streaming data.
.Ft bool
.Fn r_muta_session_set_key "RMutaSession *cj" "const ut8 *key" "int keylen" "int mode" "int direction"
.Pp
Configures the cryptographic key and direction (encrypt/decrypt) for the session. Return value indicates whether the plugin accepted the key (for example invalid key size will fail).
.Pp
.Ft bool
.Fn r_muta_session_set_iv "RMutaSession *cj" "const ut8 *iv" "int ivlen"
.Pp
Sets the initialization vector used by block cipher modes such as CBC.
.Sh PROCESSING
Streaming APIs allow sending data in chunks. Use `r_muta_session_update` for intermediate chunks and `r_muta_session_end` for the last chunk; some plugins treat `end` as a way to finalize padding or state.
.Ft bool
.Fn r_muta_session_update "RMutaSession *cj" "const ut8 *buf" "int len"
.Pp
Feeds `len` bytes from `buf` into the session for processing. Returns true on success.
.Pp
.Ft bool
.Fn r_muta_session_end "RMutaSession *cj" "const ut8 *buf" "int len"
.Pp
Finalizes processing. Can accept a final chunk (or `NULL, 0`) to finish and flush internal buffers.
.Pp
.Ft int
.Fn r_muta_session_append "RMutaSession *cj" "const ut8 *buf" "int len"
.Pp
Internal helper used by plugins to append produced bytes to the session output buffer. Callers usually do not need to use this directly.
.Sh OUTPUT
After the session ends (or at any point the plugin exposes output), retrieve the produced bytes with `r_muta_session_get_output`. The returned buffer is heap allocated and must be freed by the caller.
.Ft ut8 *
.Fn r_muta_session_get_output "RMutaSession *cj" "int *size"
.Pp
Returns a newly allocated buffer containing the processed output and sets `*size` to the buffer length. The caller is responsible for `free()`ing it.
.Sh PLUGINS
The context can be extended with plugins or inspected to enumerate supported algorithms. Plugins implement a small vtable of callbacks (set_key, update, end, etc.).
.Ft bool
.Fn r_muta_add "RMuta *cry" "RMutaPlugin *h"
.Pp
Registers a plugin into the context. Plugins provided in the tree are automatically added by `r_muta_init` called from `r_muta_new`.
.Pp
.Ft char *
.Fn r_muta_list "RMuta *cry" "RMutaType type" "int mode"
.Pp
Returns a new string listing available plugins of `type` (for example `R_MUTA_TYPE_CRYPTO` or `R_MUTA_TYPE_HASH`). The returned string must be freed by the caller.
.Sh MODES AND DIRECTIONS
Plugins accept modes and directions to control behavior; common values are `R_CRYPTO_DIR_ENCRYPT` and `R_CRYPTO_DIR_DECRYPT`. Modes cover block cipher modes such as ECB, CBC, OFB, and CFB. Choose the direction consistently when calling `r_muta_session_set_key`.
.Sh ALGORITHMS
A number of built-in plugins are available (AES, DES, Blowfish, RC2/4/6, XOR, ROT/ROL/ROR, base64/base91, bech32, punycode, ed25519, entropy, various hash algorithms). Use `r_muta_list()` to discover what is available in the running build.
.Sh EXAMPLES
This section shows idiomatic, real-world usages of the API. The first example demonstrates how `libr/muta/hash/hash.c` uses r_muta to implement algorithm-agnostic hashing in `r_hash_tostring` (see `libr/muta/hash/hash.c`).
.Bd -literal -offset indent
/* Example: computing a hash using a plugin when available
 * See: libr/muta/hash/hash.c
 */
RMuta *cry = r_muta_new();
RMutaSession *cj = r_muta_use (cry, name); // name like "sha1" or "md5"
int digest_size = 0;
if (cj && cj->h->type == R_MUTA_TYPE_HASH) {
    r_muta_session_update (cj, data, len);
    ut8 *result = r_muta_session_get_output (cj, &digest_size);
    if (result) {
        memcpy (ctx->digest, result, digest_size);
        free (result);
    }
} else {
    /* fallback to internal r_hash implementation */
}
r_muta_session_free (cj);
r_muta_free (cry);
.Ed
.Pp
The AES example below follows the lifecycle for a cipher plugin, showing key and IV setup, streaming update and finalization. The pattern is taken from `libr/muta/p/muta_aes.c` and how sessions are consumed by callers.
.Bd -literal -offset indent
RMuta *cry = r_muta_new();
RMutaSession *s = r_muta_use (cry, "aes-cbc");
if (!s) { /* handle error */ }
// Set a 128/192/256-bit key; direction is R_CRYPTO_DIR_ENCRYPT
ut8 key[16] = { /* ... */ };
ut8 iv[16]  = { /* ... */ };
if (!r_muta_session_set_key (s, key, sizeof key, R_CRYPTO_MODE_CBC, R_CRYPTO_DIR_ENCRYPT)) {
    /* invalid key or plugin refused */
}
if (!r_muta_session_set_iv (s, iv, sizeof iv)) {
    /* invalid iv */
}
// Stream plaintext
r_muta_session_update (s, plaintext, plaintext_len);
// Finalize and flush
r_muta_session_end (s, NULL, 0);
int outlen = 0;
ut8 *cipher = r_muta_session_get_output (s, &outlen);
// use cipher, then free
free (cipher);
r_muta_session_free (s);
r_muta_free (cry);
.Ed
.Pp
Simpler transformations, such as base64 or xor, follow the same session API; set_key may be a no-op for stateless encoders. The XOR plugin demonstrates setting a small repeating key and streaming the buffer.
.Bd -literal -offset indent
RMuta *cry = r_muta_new();
RMutaSession *s = r_muta_use (cry, "xor");
ut8 key[4] = {0x41, 0x42, 0x43, 0x44};
r_muta_session_set_key (s, key, 4, 0, R_CRYPTO_DIR_ENCRYPT);
r_muta_session_update (s, data, len);
r_muta_session_end (s, NULL, 0);
int outlen = 0;
ut8 *out = r_muta_session_get_output (s, &outlen);
free (out);
r_muta_session_free (s);
r_muta_free (cry);
.Ed
.Sh NOTES
Plugins follow a vtable pattern: `RMutaPlugin` exposes callbacks such as `set_key`, `update`, `end` and `get_key_size`. Callers should:
- Create a single `RMuta` context per scope and reuse it for multiple sessions.
- Always call `r_muta_session_free` after finishing with a session.
- Free the buffer returned by `r_muta_session_get_output`.
.Sh SEE ALSO
.Xr r_hash 3

